#include "dspSimulator/instruction/SPLOOP.h"

namespace dspsimulator {

    std::string SPLOOP::to_string() const {
        return get_standard_condition(m_creg_z) + m_name + " " + std::to_string(m_ii);
    }

    std::shared_ptr<DspInstruction>
    SPLOOP::decode_standard_instruction(const std::shared_ptr<DspInstructionInfo> &dsp_instruction_info) {
        std::shared_ptr<SPLOOP> sploop;
        std::bitset<32> &data = dsp_instruction_info->m_standard_bits;
        if (common::check_bits<21>(data, 0b000001110000000000000, 2) &&
            exist_standard_condition(common::extract_bits<4>(data, 28))) {
            sploop = std::make_shared<SPLOOP>(dsp_instruction_info->address(), 4);
            sploop->m_creg_z = common::extract_bits<4>(data, 28);
            sploop->m_ii = common::extract_bits<5>(data, 23).to_ulong() + 1;
            sploop->m_p = data[0];
        }
        return sploop;
    }

    std::shared_ptr<DspInstruction>
    SPLOOP::decode_compact_instruction(const std::shared_ptr<DspInstructionInfo> &dsp_instruction_info) {
        std::shared_ptr<SPLOOP> sploop;
        std::bitset<16> &data = dsp_instruction_info->m_compact_bits;
        if (common::check_bits<6>(data, 0b110011, 1) && common::check_bits<4>(data, 0b0011, 10) && !data[15]) {
            sploop = std::make_shared<SPLOOP>(dsp_instruction_info->address(), 2);
            u32 ii = common::extract_bits<1>(data, 14).to_ulong() << 3;
            ii += common::extract_bits<3>(data, 7).to_ulong();
            bool op = data[0];
            ii = op ? ii : ii + 1;
            sploop->m_ii = ii;
            sploop->m_p = dsp_instruction_info->p();
        }
        return sploop;
    }
}